import logging
from flask_babel import _
from controllers.errors.error import HttpAccountNotFound
from controllers.errors.online_mall.shop_errors import HShopNotFoundError,HShopParamError
from controllers.errors.online_mall.transport_errors import HTransfeeNotFoundError, HTransportNotFoundError, HTransportParamError
from core.entities.account_role import AccountWrap
from extensions.ext_database import db

from models.account import Account
from models.online_mall.delivery import MTransCity, MTransFreeCity, MTransfee, MTransfeeFree, MTransport, TransfeeFreeType, TransportChargeType
from models.online_mall.shop_msg import (
    ShopStatus,
    MShop,
    MShopApproval
)
from werkzeug.exceptions import InternalServerError
from services.errors.account import NotLoginError
from services.file_service import FileService


class TransportTemService:
    @staticmethod
    def get_by_id(current_user,trans_id)->MTransport:
        if not current_user:
            raise NotLoginError()
        transport = db.session.get(MTransport,trans_id)
        if not transport:
            raise HTransportNotFoundError(trans_id)
        return transport
    
    @staticmethod
    def get_list(account:AccountWrap,args:dict)->dict:
        try:
            query = db.session.query(MTransport).filter(MTransport.tenant_id==account.current_tenant_id)
            if 'name' in args and args['name']:
                query = query.filter(MTransport.name.like(f"%{args['name']}%"))
            if 'shop_id' in args and args['shop_id']:
                query = query.filter(MTransport.shop_id==args['shop_id'])
            if 'charge_type' in args and args['charge_type']:
                query = query.filter(MTransport.charge_type==args['charge_type'])
            if 'is_free_fee' in args and args['is_free_fee'] is not None:
                query = query.filter(MTransport.is_free_fee==args['is_free_fee'])
            if 'has_free_condition' in args and args['has_free_condition'] is not None:
                query = query.filter(MTransport.has_free_condition==args['has_free_condition'])
            total = query.count()
            has_more = False
            if 'page' in args and args['page']>0 and 'page_size' in args and args['page_size']>0:
                query = query.offset((args['page']-1)*args['page_size']).limit(args['page_size'])
                has_more = total > args['page_size'] * args['page']
            data = query.order_by(MTransport.id.desc()).all()
            return {
                "total":total,
                "has_more":has_more,
                "data":data
            }
        except Exception as e:
            logging.error(e)
            return {
                "total":0,
                "has_more":False,
                "data":[],
                "message":str(e)
            }
        
    @staticmethod
    def create_temp(account:AccountWrap,args:dict)->MTransport:
        transport = MTransport(
            tenant_id = account.current_tenant_id, # type:ignore
            created_by = account.id, # type:ignore
        )
        TransportTemService._fill_transport_param(args, transport)
        try:
            db.session.add(transport)
            db.session.commit()
            transport = db.session.get(MTransport,transport.id)
            if not transport:
                raise HTransportNotFoundError(None)
            return transport
        except Exception as e:
            db.session.rollback()
            raise e
        
    @staticmethod
    def update_temp(account:AccountWrap,args:dict)->MTransport:
        trans_id = args.get('id',None)
        if not trans_id:
            raise HTransportNotFoundError(trans_id)
        transport = db.session.get(MTransport,trans_id)
        if not transport or transport.tenant_id != account.current_tenant_id:
            raise HTransportNotFoundError(trans_id)
        TransportTemService._fill_transport_param(args, transport)
        try:
            db.session.commit()
            transport = db.session.get(MTransport,transport.id)
            if not transport:
                raise HTransportNotFoundError(None)
            return transport
        except Exception as e:
            db.session.rollback()
            raise e
    @staticmethod
    def delete_temp(account:AccountWrap,args:dict):
        trans_id = args.get('id',None)
        if not trans_id:
            raise HTransportNotFoundError(trans_id)
        transport = db.session.get(MTransport,trans_id)
        if not transport or transport.tenant_id != account.current_tenant_id:
            raise HTransportNotFoundError(trans_id)
        
        try:
            for transfee_free in transport.transfee_frees:
                city_ids = transfee_free.city_ids
                db.session.query(MTransFreeCity).filter(MTransFreeCity.transfee_free_id==transfee_free.id,MTransFreeCity.city_id.in_(city_ids)).delete()
                db.session.delete(transfee_free)
            for transfee in transport.transfees:
                city_ids = transfee.city_ids
                db.session.query(MTransCity).filter(MTransCity.transfee_id==transfee.id,MTransCity.city_id.in_(city_ids)).delete()
                db.session.delete(transfee)
            db.session.delete(transport)
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            raise e
        
    @staticmethod
    def _fill_transport_param(args:dict, transport:MTransport):
        if 'shop_id' in args and args['shop_id']:
            transport.shop_id = args['shop_id']
            shop = db.session.get(MShop,args['shop_id'])
            if not shop:
                raise HShopNotFoundError(args['shop_id'])
        if 'charge_type' in args and args['charge_type']:
            charge_type = TransportChargeType(args['charge_type'])
            if not charge_type:
                raise HTransportParamError(_("Charge type is invalid"))
        if 'is_free_fee' in args and args['is_free_fee'] is not None:
            transport.is_free_fee = args['is_free_fee']
        if 'has_free_condition' in args and args['has_free_condition'] is not None:
            transport.has_free_condition = args['has_free_condition']
        transfees = args.get('transfees',[])
        transfees_list = []

        for transfee_dict in transfees:
            if 'id' in transfee_dict and transfee_dict['id']:
                transfee = db.session.get(MTransfee,transfee_dict['id'])
                if not transfee:
                    raise HTransfeeNotFoundError(transfee_dict['id'])
                is_new = False
            else:
                transfee = MTransfee(
                    transport_id=transport.id,
                    continuous_piece=transfee_dict['continuous_piece'],
                    first_piece=transfee_dict['first_piece'],
                )
                db.session.add(transfee)
                db.session.flush()
                is_new = True
            transfee.ContinuousFee = transfee_dict['ContinuousFee']
            transfee.FirstFee = transfee_dict['FirstFee']
            transfees_list.append(transfee_dict)
            for city_id in transfee_dict['city_ids']:
                if is_new: 
                    transcity = MTransCity(
                        transfee_id=transfee.id, # type:ignore
                        city_id=city_id # type:ignore
                    )
                    db.session.add(transcity)
                    db.session.flush()
                else:
                    transcity = db.session.query(MTransCity).filter(MTransCity.transfee_id==transfee.id,MTransCity.city_id==city_id).first()
                    if not transcity:
                        transcity = MTransCity(
                            transfee_id=transfee.id, # type:ignore
                            city_id=city_id # type:ignore
                        )
                        db.session.add(transcity)
                        db.session.flush()
            db.session.query(MTransCity).filter(MTransCity.transfee_id==transfee.id,~MTransCity.city_id.in_(transfee_dict['city_ids'])).delete()

        transfee_frees = args.get('transfee_frees',[])
        for transfee_free_dict in transfee_frees:
            if 'id' in transfee_free_dict and transfee_free_dict['id']:
                transfee_free = db.session.get(MTransfeeFree,transfee_free_dict['id'])
                if not transfee_free:
                    raise HTransfeeNotFoundError(transfee_free_dict['id'])
                is_new = False
            else:
                transfee_free = MTransfeeFree(
                    transport_id=transport.id, # type:ignore
                    piece=transfee_free_dict['piece'], # type:ignore
                )
                db.session.add(transfee_free)
                db.session.flush()
                is_new = True
            free_type = TransfeeFreeType(transfee_free_dict['free_type'])
            if free_type:
                transfee_free.free_type = free_type.value
            amount = float(transfee_free_dict['Amount'])
            transfee_free.Amount = amount
            for city_id in transfee_free_dict['city_ids']:
                if is_new: 
                    transcity_free = MTransFreeCity(
                        transfee_free_id=transfee_free.id, # type:ignore
                        city_id=city_id # type:ignore
                    ) 
                    db.session.add(transcity_free)
                    db.session.flush()
                else:
                    transcity_free = db.session.query(MTransFreeCity).filter(MTransFreeCity.transfee_free_id==transfee_free.id,MTransFreeCity.city_id==city_id).first()
                    if not transcity_free:
                        transcity_free = MTransFreeCity(
                            transfee_free_id=transfee_free.id, # type:ignore
                            city_id=city_id # type:ignore
                        )
                        db.session.add(transcity_free)
                        db.session.flush()
            db.session.query(MTransFreeCity).filter(MTransFreeCity.transfee_free_id==transfee_free.id,~MTransFreeCity.city_id.in_(transfee_free_dict['city_ids'])).delete()